EC2 Instance Connect Endpoint経由でRDSに接続してみた
2023/06/28 追記 : 利用可能ポートが制限されました
公開当時の内容
しばたです。
前に書いた記事でEC2 Instance Connect Endpointの接続はWebSocketトンネルを介したものであると説明しました。
また、プロトコルもSSHだけに制限されておらずRDPも使用可能でした。
- AWS CLIの実装からEC2 Instance Connect Endpointを読み解いてみた
- EC2 Instance Connect Endpoint経由でWindows ServerにRDP接続してみた
AWS CLIの実装を読み解く限りこの機能のメインはWebSocketトンネルを張る事でありプロトコルにも依存していません。
そうなると「別にEC2インスタンスに限らず、たとえばRDSインスタンスに対してもトンネルを張れるのでは?」と考えるのは必然でしょう。
試してみた
というわけで実際に試してみました。
検証環境
前回の記事で用意したVPC環境にRDS for PostgreSQL 15.3のインスタンスを用意しました。
RDS for PostgreSQLを選んだのは単純に私が使い慣れてるだけであり他のRDBMSでも問題ないでしょう。
その他の情報は以下の通りです。
- VPC内のPrivateサブネットはインターネットアクセス不可
- RDS for PostgreSQL 15.3はSingle AZ構成で待ち受けポートはデフォルトのまま(TCP 5432)
- パラメーターグループとオプショングループはデフォルトのものを使用
- セキュリティグループでVPC Endpointからの接続(TCP 5432)を許可
- VPC EndpointのセキュリティグループでTCP 5432のアウトバウンド通信を許可
- クライアント環境でAWS CLIを利用可能に初期設定済み
your_profile
という名前のプロファイルを設定済み
補足1 : VPC Endpointのセキュリティグループ設定
VPC Endpointセキュリティグループのアウトバウンド通信制御はこんな感じになっていればOKです。
RDSインスタンスに対してTCP 5432で通信するためアウトバウンド通信を許可しておきます。
インバウンド通信は全てブロックして構いません。
補足2 : RDSインスタンスのセキュリティグループ設定
RDSインスタンス側のセキュリティグループはVPC Endpointからのインバウンド通信を許可しておきます。
1. aws ec2-instance-connect open-tunnel コマンドの実行
接続までの手順はWindows ServerにRDP接続した時とほぼ同じです。
最初にクライアントでaws ec2-instance-connect open-tunnel
コマンドを使用しRDSインスタンスに対してWebSocketトンネルを張ります。
このコマンドの基本的な使い方は--instance-id
パラメーターで宛先EC2インスタンスIDを指定しており、このままではRDSに接続できません。
# EC2インスタンスIDを指定してWebSocketトンネルを張る
aws ec2-instance-connect open-tunnel --instance-id "宛先インスタンスID" --remote-port 3389 --local-port "任意の空きポート"
上記指定をした際は
- 宛先インスタンス情報からインスタンスのPrivate IPアドレスを取得
- 宛先インスタンスの配置されているVPCおよびサブネット情報からVPC Endpointを探索する
といった作業を内部で行っています。
WebSocketトンネルを張るのに必要な情報は「VPC EndpointのPublic DNS名」「宛先Private IPアドレス」「宛先ポート番号」「ローカルポート番号」であり、このうち「VPC EndpointのPublic DNS名」「宛先Private IPアドレス」の2つをどうにかしてコマンドに渡してやる必要があります。
「宛先Private IPアドレス」はRDSのDNSエンドポイントを名前解決してやれば取得できます。
# 例えばPowerShellからだとこんな感じでRDSの名前解決が可能 : 今回の環境では 10.0.21.157 がRDSのIPアドレス
PS C:\> Resolve-DnsName -Name test-postgres.xxxxxxxxxx.ap-northeast-1.rds.amazonaws.com -Type A | Select-Object IPAddress
IPAddress
---------
10.0.21.157
そしてありがたいことにこのコマンドには--instance-connect-endpoint-id
, --private-ip-address
パラメーターが存在しています。
「VPC EndpointのPublic DNS名」は--instance-connect-endpoint-id
を指定してやればコマンド内部で取得してくれます。[1]
このため以下の指定でWebSocketトンネルを張ることができます。
# VPC Endpoint IDおよび宛先Private IPアドレスを直接指定してトンネルを張ることも可能
aws ec2-instance-connect open-tunnel --instance-connect-endpoint-id "VPC Endpoint ID"--private-ip-address "宛先Private IP"--local-port "任意の空きポート" --remote-port 5432
実行例はこんな感じ。
# 今回の実行例
PS C:\> $env:AWS_PROFILE="your_profile"
PS C:\> aws ec2-instance-connect open-tunnel --instance-connect-endpoint-id eice-xxxxxxxxxxxx --private-ip-address 10.0.21.157 --local-port 15432 --remote-port 5432
設定に問題がなければエラー無くWebSocketトンネルが張れるはずです。
2. RDSインスタンスへ接続
あとはlocalhost:15432 (127.0.0.1:15432)
に接続すればPostgreSQLを操作できます。
(pgAdmin 4で接続する場合)
(VPC EndpointのIP 10.0.21.136 から接続された扱いになっている)
最後に
以上となります。
今回はRDSを例にしましたがVPCからIPv4で到達可能であれば様々なAWSリソースに対して接続できるはずです。
無限に応用できると思いますので是非活用してみてください。
ちなみに--instance-connect-endpoint-dns-nameパラメーターも存在し、直接Public DNS名を引き渡すことも可能です ↩︎